﻿#include <iostream>
#include <windows.h>
#include <conio.h>
#include <stdio.h>
#include <time.h>
#include <string>

#include "Card.h"
#include "Deck.h"
#include "Hand.h"

#define $DRAW std::cout
#define █ <<(char)219
#define s <<" "
#define e <<std::endl
#define ╔ <<(char)201
#define ═ <<(char)205
#define ╗ <<(char)187
#define ║ <<(char)186
#define ╚ <<(char)200
#define ╝ <<(char)188
#define ♥ <<(char)3
#define ♦ <<(char)4
#define ♣ <<(char)5
#define ♠ <<(char)6

#define $nombredejoueurs <<"Nombre de joueurs : "<<NumberPlayer

#define MaxNo_Menu 2
#define MaxNo_BetMenu 5
#define MaxNo_PlayMenu 3

const int STARTING_MONEY = 1000;bool isMenu = true;
HANDLE con=GetStdHandle(STD_OUTPUT_HANDLE);	

using namespace std;

int AskBet(int& money, int& playerTurn);
int Bet(int& money, int& bet, int& playerTurn);
void InitGame(int &numberPlayer);
void TitleScreen();
void DisplayTable(hand& Hand_Player1, hand& Hand_Player2, hand& Hand_Dealer, hand& Hand_Split1, hand& Hand_Split2, int numberPlayer);
void GiveCard(hand& h, deck& d);
void whatamidoingwithmylife();
void CalculateScore(hand h, int &playerScore);
bool AskPlayer(int playerScore, int playerScoreSplit, hand& h, hand& sh, deck& d, int& playerTurn);
bool AskSplit(hand& h, hand& sh, deck& d, int& playerTurn);
bool AskTire(int playerScore, hand& h, deck& d, bool& end, int& playerTurn);
bool AskAI(int& dealerScore, hand& h, deck& d);
void InitMenu(int &numberPlayer);
void goToXY(int x, int y);
void textAttribut(int color);
void CheckVictory(int playerScore1, int playerScore1Split, int playerScore2, int playerScore2Split, int dealerScore, int &player1Money, int &player2Money,int bet1,int bet2);

int main()
{
	bool End = false, GameOver = false;
	int playerTurn = 1;
	int numberPlayer = 0;
	int player1Money = STARTING_MONEY;
	int player2Money = STARTING_MONEY;
	int playerScore1 = 0;
	int playerScore1Split = 0;
	int playerScore2 = 0;
	int playerScore2Split = 0;
	int dealerScore = 0;
	int player1Bet ,player2Bet;
	bool turn[3];

	InitGame(numberPlayer);
	player1Money = STARTING_MONEY;
	player2Money = STARTING_MONEY;

	while(!End) // Quand l'argent de un des joueurs est a 0
	{
		/**/
		deck Deck_1;
		InitDeck(Deck_1);
		ShuffleDeck(Deck_1);
		hand Hand_Player1, Hand_Player2, Hand_Dealer;
		hand Hand_Split1, Hand_Split2;
		InitHand(Hand_Player1);
		GiveHand(Hand_Player1, Deck_1);
		InitHand(Hand_Player2);
		GiveHand(Hand_Player2, Deck_1);
		InitHand(Hand_Dealer);
		GiveHand(Hand_Dealer, Deck_1);
		InitHand(Hand_Split1);
		InitHand(Hand_Split2);
		/**/
		
		if(numberPlayer == 1)
		{
			do
			{
				player1Bet = AskBet(player1Money, playerTurn);
			}while(player1Bet == 0);
		}
		else
		{
			do
			{
				player1Bet = AskBet(player1Money, playerTurn);
			}while(player1Bet == 0);
			playerTurn = 2;
			do
			{
				player2Bet = AskBet(player2Money, playerTurn);
			}while(player2Bet == 0);
		}

		GameOver = false;

		while(!GameOver)  // Quand le tour est terminé
		{
			for(int i = 0; i < 3; i++)
				turn[i] = false;

			DisplayTable(Hand_Player1, Hand_Player2, Hand_Dealer, Hand_Split1, Hand_Split2, numberPlayer);

			// init player1
			CalculateScore(Hand_Player1, playerScore1);
			std::cout << "Player one cards value : " << playerScore1 << std::endl;
			if(Hand_Split1.nbCards > 0)
			{
				CalculateScore(Hand_Split1, playerScore1Split);
				std::cout << "Player one SplitDeck value : " << playerScore1Split << std::endl;
			}
			// init player2
			if(numberPlayer == 2)
			{
				CalculateScore(Hand_Player2,playerScore2);
				std::cout << "Player two cards value : " << playerScore2 << std::endl;
				if(Hand_Split1.nbCards > 0)
				{
					CalculateScore(Hand_Split2, playerScore2Split);
					std::cout << "Player two SplitDeck value : " << playerScore2Split << std::endl;
				}
			}

			// Player 1
			while(!turn[0])
			{
				playerTurn = 1;
				turn[0] = AskPlayer(playerScore1, playerScore1Split, Hand_Player1, Hand_Split1, Deck_1, playerTurn);
				CalculateScore(Hand_Player1, playerScore1);
				DisplayTable(Hand_Player1, Hand_Player2, Hand_Dealer, Hand_Split1, Hand_Split2, numberPlayer);
				std::cout << "Player one cards value : " << playerScore1 << std::endl;
				if(Hand_Split1.nbCards > 0)
				{
					CalculateScore(Hand_Split1, playerScore1Split);
					std::cout << "Player one SplitDeck value : " << playerScore1Split << std::endl;
				}
			}

			if(numberPlayer == 2)
			{
				while(!turn[1])
				{
					playerTurn = 2;
					turn[1] = AskPlayer(playerScore2, playerScore2Split, Hand_Player2, Hand_Split2, Deck_1, playerTurn);
					CalculateScore(Hand_Player2, playerScore2);
					DisplayTable(Hand_Player1, Hand_Player2, Hand_Dealer, Hand_Split1, Hand_Split2, numberPlayer);
					std::cout << "Player Two cards value : " << playerScore2 << std::endl;
					if(Hand_Split1.nbCards > 0)
					{
						CalculateScore(Hand_Split2, playerScore2Split);
						std::cout << "Player Two SplitDeck value : " << playerScore2Split << std::endl;
					}
				}
			}

			//dealer
			while(!turn[2])
			{
				CalculateScore(Hand_Dealer, dealerScore);
				turn[2] = AskAI(dealerScore, Hand_Dealer, Deck_1);
				DisplayTable(Hand_Player1, Hand_Player2, Hand_Dealer, Hand_Split1, Hand_Split2, numberPlayer);
				std::cout << "Dealer's cards value : " << dealerScore << std::endl;
			}

			CalculateScore(Hand_Dealer, dealerScore);
			DisplayTable(Hand_Player1, Hand_Player2, Hand_Dealer, Hand_Split1, Hand_Split2, numberPlayer);

			std::cout << "Player one cards value : " << playerScore1 << std::endl;
			if(Hand_Split1.nbCards > 0)
				std::cout << "Player one split cards value : " << playerScore1Split << std::endl;
			if(numberPlayer == 2)
			{
				std::cout << "Player two cards value : " << playerScore2 << std::endl;
				if(Hand_Split1.nbCards > 0)
					std::cout << "Player two split cards value : " << playerScore2Split << std::endl;
			}
			std::cout << "Dealer's cards value : " << dealerScore << std::endl;

			Sleep(3000);

			CheckVictory(playerScore1, playerScore1Split, playerScore2, playerScore2Split, dealerScore, player1Money, player2Money, player1Bet, player2Bet);

			GameOver = true;
		}
	}
	return 0;
}

void InitGame(int &numberPlayer)
{
	bool validInput = false;
	string input;

	// hides the cursor 
	HANDLE hConsoleOutput;
	CONSOLE_CURSOR_INFO structCursorInfo;
	hConsoleOutput = GetStdHandle( STD_OUTPUT_HANDLE );
	GetConsoleCursorInfo(hConsoleOutput, &structCursorInfo );
	structCursorInfo.bVisible = FALSE;
	SetConsoleCursorInfo(hConsoleOutput, &structCursorInfo );

	system("color fD");
	srand(time(NULL));

	TitleScreen();
	InitMenu(numberPlayer);
}

void InitMenu(int &numberPlayer)
{
	char *menu_list[MaxNo_Menu] = { "Jouer seul", "Jouer a deux"};
	int i,
	xpos = 2,
	ypos[MaxNo_Menu] = { 14, 16};
	 
	// Menu
	for (i = 0; i < MaxNo_Menu; ++i)
	{
	    goToXY(xpos, ypos[i] );
	    //13 = pink
		textAttribut(13);
		
		cout << menu_list[i] << endl;
	}
	 
	// Choose menu
	i = 0;
	while(isMenu)
	{
	    goToXY(xpos, ypos[i]);
		//9 == blue
	    textAttribut(9);
	    cout << menu_list[i] << endl;
	 
	    // 72 -> UP button
	    // 80 -> DOWN button
		switch( _getch() )
		{
		case 72:	
			if(i > 0) 
			{
				goToXY(xpos, ypos[i] );
				// 13 = pink
				textAttribut(13);
				cout << menu_list[i] << endl;
				--i;
			}
			break;
		case 80:	
			if(i < MaxNo_Menu - 1 )
			{
				goToXY(xpos, ypos[i]);
				textAttribut(13);
				cout << menu_list[i] << endl;
				++i;
			}
			break;
		case 13:	
			if(i == 0) 
			{
				// jouer seul
				system("cls");
				isMenu = false;
				numberPlayer = 1;
			}
			if(i == 1) 
			{
				//jouer a 2
				system("cls");
				isMenu = false;
				numberPlayer = 2;
			}
		}
	}
}

void DisplayTable(hand& Hand_Player1, hand& Hand_Player2, hand& Hand_Dealer, hand& Hand_Split1, hand& Hand_Split2, int numberPlayer)
{
	textAttribut(13);
	system("cls");

	// dealer
	if(Hand_Dealer.nbCards > 2)
	{
		ShowHand(Hand_Dealer);
	}
	else
	{
		ShowDealer(Hand_Dealer);
	}

	// split
	if(Hand_Split1.nbCards > 0 || Hand_Split2.nbCards > 0)
	{
		if(Hand_Split1.nbCards > 0 && Hand_Split2.nbCards > 0)
		{
			ShowHand(Hand_Split1, Hand_Split2);
		}
		else if(Hand_Split1.nbCards > 0)
		{
			ShowHand(Hand_Split1);
		}
		else
		{
			ShowHand(Hand_Split2);
		}
	}
	// hands
	if(numberPlayer == 1)
	{
		ShowHand(Hand_Player1);
	}	
	else
	{
		ShowHand(Hand_Player1, Hand_Player2);
	}
}

void GiveCard(hand& h, deck& d)
{
	h.HandCards[h.nbCards] = d.Cards[0];
	h.nbCards++;
	RemoveCard(d);
}	

void CalculateScore(hand h, int &playerScore)
{
	int cardValue = 0;
	int finalScore = 0;
	bool unAs = false;

	for (int j = 0; j < h.nbCards; j++)
	{
		if(h.HandCards[j].Number == 65)
		{
			h.HandCards[j].Number = 1;
		}
		else if(h.HandCards[j].Number == 74 || h.HandCards[j].Number == 81 || h.HandCards[j].Number == 75 || h.HandCards[j].Number == 84)
		{
			h.HandCards[j].Number = 10;
		}
		else
		{
			h.HandCards[j].Number -= 48;
		}
	}

	for(int i = 0; i < h.nbCards; i++)
	{
		if(h.HandCards[i].Number == 1)
		{
			cardValue = 11;
			unAs = true;
		}
		else if(h.HandCards[i].Number >= 10)
		{
			cardValue = 10;
		}
		else
		{
			cardValue = h.HandCards[i].Number;
		}
		finalScore += cardValue;
	}

	if(finalScore > 21)
	{
		if(unAs)
		{
			finalScore -=10;
		}
	}

	playerScore = finalScore;
}

int AskBet(int& money, int& playerTurn)
{
	int bet = 0; 
	do 
	{
		bet = 0;
		system("cls");
		bet = Bet(money, bet, playerTurn);	
	}while(bet > money);
	money -= bet;

	return bet;
}
	
int Bet(int& money, int& bet, int& playerTurn)
{
	bool isBet = false;	 

	textAttribut(13);
	if(playerTurn == 1)
	{
		cout<< "Joueur 1" << endl;
	}
	if(playerTurn == 2)
	{
		cout << "Joueur 2" << endl;
	}
	cout << "Combien voulez-vous miser?" << endl;
	cout << "Vous avez " << money << "$" << endl;
	 
	char *menu_list[MaxNo_BetMenu] = { "5$", "10$", "25$", "100$", "Miser"};
	int i,
	 xpos = 10,
	 ypos[MaxNo_BetMenu] = {3, 4, 5, 6,7};
	 
	// Menu
	for (i = 0; i < MaxNo_BetMenu; ++i)
	{
	    goToXY(xpos, ypos[i]);
	    textAttribut(13);
		cout << menu_list[i] << endl;
	}
	 
	// Choose Menu
	i = 0;
	while(!isBet)
	{
	    goToXY(xpos, ypos[i]);
	    textAttribut(9);
	    cout << menu_list[i] << endl;
	 
	    // 72 -> UP button
	    //80 -> DOWN button
		switch( _getch() )
		{
		case 72: 
			if(i > 0) 
			{
				goToXY(xpos, ypos[i]);
				textAttribut(13);
				cout << menu_list[i] << endl;
				--i;
			}
			break;
		case 80: 
			if(i < MaxNo_BetMenu - 1 )
			{
				goToXY(xpos, ypos[i]);
				textAttribut(13);
				cout << menu_list[i] << endl;
				++i;
			}
			break;
		case 13: 
			if(i == 0) 
			{
				//mise +5
				bet += 5;
				goToXY(1,3);
				cout << bet<< endl;
			}
			if(i == 1) 
			{
				//mise +10
				bet += 10;
				goToXY(1, 3);
				cout << bet << endl; 
			}
			if(i == 2) 
			{
				//mise +25
				bet += 25;
				goToXY(1, 3);cout << bet << endl;  
			}
			if(i == 3) 
			{
				//mise +100
				bet += 100;
				goToXY(1, 3);cout << bet << endl;  
			}
			if(i == 4) 
			{
				//retourne la mise finale
				isBet = true;  
			}
			if(isBet)
			{
				return bet;
			}
		}
	}
}

bool AskPlayer(int playerScore, int playerScoreSplit, hand& h, hand& sh, deck& d, int& playerTurn)
{
	bool endTurn = false;
	bool split = false;
	bool tire = false;
	bool tireSplit = false;

	split = AskSplit(h, sh, d, playerTurn);

	if(!split)
	{
		tire = AskTire(playerScore, h, d, endTurn, playerTurn);
	}
	else
	{
		return endTurn;
	}

	if(!tire)
	{
		if(sh.nbCards > 0)
		{
			tireSplit = AskTire(playerScoreSplit, sh, d, endTurn, playerTurn);
		}
		else
		{
			tireSplit = true;
		}
		if(tireSplit)
		{
			endTurn = true;
		}
	}
	return endTurn;
}

bool AskTire(int playerScore, hand& h, deck& d, bool& end, int& playerTurn)
{
	bool tire = false;

	textAttribut(13);
	if(playerScore < 21)
	{
		tire = true;
		bool choice = false;
		if(playerTurn == 1)
		{
			cout << "Joueur 1" << endl;
		}
		if(playerTurn == 2)
		{
			cout << "Joueur 2" << endl;
		}
		cout << "Voulez-vous tirer une carte?" << endl;
		char *menu_list[MaxNo_PlayMenu] = { "oui", "non", "abandonner"};
		int i,
		xpos = 2,
		ypos[MaxNo_PlayMenu] = {18, 19, 21};

		// Menu
		for (i = 0; i < MaxNo_PlayMenu; ++i)
		{
			goToXY(xpos, ypos[i]);
			textAttribut(13);
			cout << menu_list[i] << endl;
		}

		// Choose menu
		i = 0;
		while(!choice)
		{
			goToXY(xpos, ypos[i]);
			textAttribut(9);
			cout << menu_list[i] << endl;
			switch( _getch() )
			{
			case 72: 
				if(i > 0) 
				{
					goToXY(xpos, ypos[i]);
					textAttribut(13);
					cout << menu_list[i] << endl;
					--i;
				}
				break;
			case 80: 
				if(i < MaxNo_PlayMenu - 1 )
				{
					goToXY(xpos, ypos[i]);
					textAttribut(13);
					cout << menu_list[i] << endl;
					++i;
				}
				break;
			case 13: 
				if(i == 0) 
				{
					// oui 
					GiveCard(h, d);
					choice = true;
				}
				if(i == 1) 
				{
					end = true;
					return tire;
				}
				if(i == 2)
				{
					end = true;
					return tire;
				}
			}
		} 	
	}
	return tire;
}

bool AskSplit(hand& h, hand& sh, deck& d, int& playerTurn)
{
	bool split = false;

	textAttribut(13);
	if(h.HandCards[0].Number == h.HandCards[1].Number)
	{
		split = true;
		bool choice = false;
		if(playerTurn == 1)
		{
			cout << "Joueur 1" << endl;
		}
		if(playerTurn == 2)
		{
			cout << "Joueur 2" << endl; 
		}
		cout << "Voulez-Vous spliter?" << endl;
		char *menu_list[MaxNo_PlayMenu] = { "oui", "non", "abandonner"};
		int i,
		xpos = 2,
		ypos[MaxNo_PlayMenu] = {18, 19, 21};

		// Menu
		for (i = 0; i < MaxNo_PlayMenu; ++i)
		{
			goToXY(xpos, ypos[i]);
			textAttribut(13);
			cout << menu_list[i] << endl;
		}

		// Choose menu
		i = 0;
		while(!choice)
		{
			goToXY(xpos, ypos[i]);
			textAttribut(9);
			cout << menu_list[i] << endl;
			switch( _getch() )
			{
			case 72: 
				if(i > 0) 
				{
					goToXY(xpos, ypos[i]);
					textAttribut(13);
					cout << menu_list[i] << endl;
					--i;
				}
				break;
			case 80: 
				if(i < MaxNo_PlayMenu - 1 )
				{
					goToXY(xpos, ypos[i]);
					textAttribut(13);
					cout << menu_list[i] << endl;
					++i;
				}
				break;
			case 13: 
				if(i == 0) 
				{
					choice = true;
					SplitHand(h, sh);
					GiveCard(sh, d);
					GiveCard(h, d);
				}
				if(i == 1) 
				{
					choice = true;
				}
				if(i == 2)
				{
					choice = true;
				}
			}
		} 	
	}
	return split;
}

bool AskAI(int& dealerScore, hand& h, deck& d)
{
	Sleep(1000);
	bool endTurn = false;

	if (dealerScore >= 17)
	{
		endTurn = true;
	}
	else if(dealerScore >= 21)
	{
		endTurn = true;
	}
	else
	{
		GiveCard(h, d);
	}
	return endTurn;
}

void CheckVictory(int playerScore1, int playerScore1Split, int playerScore2, int playerScore2Split, int dealerScore, int &player1Money, int &player2Money,int bet1,int bet2)
{
	bool multipleWinners = false;

	//POUR LES BLACKJACKS OU LES 21
	//si joueur 1 et 2 sont a égalité
	if(playerScore1 == 21 && playerScore2 == 21 && dealerScore != 21)
	{
		player1Money += (bet1 * 2)/2;
		player2Money += (bet2 * 2)/2;
		multipleWinners = true;
	}
	//si le joueur 1 et le dealer sont a égalité
	if(playerScore1 == 21 && dealerScore == 21 && playerScore2 != 21)
	{
		player1Money += (bet1 * 2) /2;
		multipleWinners = true;
	}
	//si le joueur 2 et le dealer sont a égalité
	if(playerScore2 == 21 && dealerScore == 21 && playerScore1 != 21)
	{
		player2Money += (bet2 * 2) /2;
		multipleWinners = true;
	}

	//si les 3 ont un blackjack
	if(playerScore1 == 21 && playerScore2 == 21 && dealerScore == 21)
	{
		player1Money += (bet1 * 2)/3;
		player2Money += (bet2 * 2)/3;
		multipleWinners = true;
	}
	//si le joueur 1 est le seul gagnant
	else if(playerScore1 == 21 && !multipleWinners)
	{
		player1Money += bet1 * 2; 
	}
	//si le joueur 2 est le seul gagnant
	else if(playerScore2 == 21 && !multipleWinners)
	{
		player2Money += bet2 * 2;
	}
	//si le dealer est le seul gagnant
	else
	{
		return;
	}

	//POUR LES GAGNANTS SANS BLACKJACK OU 21

	if(playerScore1 < 21)
	{
		if(dealerScore > 21)
		{
			player1Money += bet1 * 2;
		}
		else if(playerScore1 > dealerScore && dealerScore < 21)
		{
			player1Money += bet1 * 2;
		}
	}
	if(playerScore2 < 21)
	{
		if(dealerScore > 21)
		{
			player2Money += bet2 * 2;
		}
		else if(playerScore2 > dealerScore && dealerScore < 21)
		{
			player2Money += bet2 * 2;
		}
	}
}

void goToXY(int x, int y)
{
	COORD Coord;
	Coord.X = x;
    Coord.Y = y;
	 
	SetConsoleCursorPosition(con, Coord);
}

void textAttribut(int color)
{
	SetConsoleTextAttribute(con, BACKGROUND_INTENSITY | FOREGROUND_INTENSITY |BACKGROUND_RED |
							BACKGROUND_GREEN |BACKGROUND_BLUE | color |FOREGROUND_BLUE);
}

void TitleScreen()
{
	$DRAW ╔ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ╗ e;
	$DRAW ║ s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s ║ e;
	$DRAW ║ s s █ █ █ █ s s s █ s s s s s s s █ s s s s s █ █ █ █ s █ s s s s █ s s █ █ █ █ █ s s s s █ s s s s s █ █ █ █ s █ s s s s █ s s ║ e;
	$DRAW ║ s s █ s s s █ s s █ s s s s s s █ s █ s s s █ s s s s s █ s s s █ s s s s s s █ s s s s █ s █ s s s █ s s s s s █ s s s █ s s s ║ e;
	$DRAW ║ s s █ s s s █ s s █ s s s s s s █ s █ s s s █ s s s s s █ s s █ s s s s s s s █ s s s s █ s █ s s s █ s s s s s █ s s █ s s s s ║ e;
	$DRAW ║ s s █ █ █ █ s s s █ s s s s s █ s s s █ s s █ s s s s s █ █ █ s s s s s s s s █ s s s █ s s s █ s s █ s s s s s █ █ █ s s s s s ║ e;
	$DRAW ║ s s █ s s s █ s s █ s s s s s █ █ █ █ █ s s █ s s s s s █ s s █ s s s █ s s s █ s s s █ █ █ █ █ s s █ s s s s s █ s s █ s s s s ║ e;
	$DRAW ║ s s █ s s s █ s s █ s s s s █ s s s s s █ s █ s s s s s █ s s s █ s s █ s s s █ s s █ s s s s s █ s █ s s s s s █ s s s █ s s s ║ e;
	$DRAW ║ s s █ █ █ █ s s s █ █ █ █ s █ s s s s s █ s s █ █ █ █ s █ s s s s █ s s █ █ █ █ s s █ s s s s s █ s s █ █ █ █ s █ s s s s █ s s ║ e;
	$DRAW ║ s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s ║ e;
	$DRAW ║ s s ♦ s ♣ s ♠ s ♥ s ♦ s ♣ s ♠ s ♥ s ♦ s ♣ s ♠ s ♥ s ♦ s ♣ s ♠ s ♥ s ♦ s ♣ s ♠ s ♥ s ♦ s ♣ s ♠ s ♥ s ♦ s ♣ s ♠ s ♥ s ♦ s ♣ s ♠ s ║ e;
	$DRAW ╚ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ═ ╝ e;
}